module spi (
  input             clk,
  input             csen,        //通信使能
  output reg        tx_req=1'b0, //发送数据请求
  
  input             tx_en,       //发送数据使能
  input     [7:0]   tx_data,     //发送数据
  output reg        rx_en=1'b0,       //接收数据输出使能
  output reg[7:0]   rx_data,     //接收数据输出
  
  output reg        scs=1'b1,
  output reg        sck=1'b0,
  output            sdi,
  input             sdo
);

reg [4:0]  sck_cnt=5'b11111;
reg [0:0]  sck_cnt_bit0=1'b0;
reg [0:0]  sck_r=1'b0;

reg [0:0]  csen_r=1'b1;
reg [7:0]  tx_data_r=8'hFF;  
reg [7:0]  rx_data_r=0;
reg [7:0]  tx_en_r=0;

//------------------------------------------------
//--请求发送数据
//------------------------------------------------
always@(posedge clk)                            
begin
  csen_r <=  csen;
end

always@(posedge clk)                            
begin
  if(((csen==1'b0)&&(csen_r==1'b1))||(sck_cnt==5'b10010))
    tx_req <= 1'b1;
  else
    tx_req <= 1'b0;
end

//------------------------------------------------
//--sck
//------------------------------------------------
always@(posedge clk)                            
begin
  tx_en_r <= {tx_en_r[6:0],tx_en};
end

always@(posedge clk)                            
begin
  if(tx_en_r[7])
    sck_cnt <= 5'b00000;
  else if(sck_cnt<5'b11111)
    sck_cnt <= sck_cnt + 1'b1;
end

always@(posedge clk)                            
begin
  if(sck_cnt<=5'b01111)
    sck_cnt_bit0 <=  sck_cnt[0];
  else if(sck_cnt >= 5'b10111)
    sck_cnt_bit0 <= 1'b0;
  else if((sck_cnt > 5'b01111)&&(csen_r==1'b1))
    sck_cnt_bit0 <= 1'b0;
  else
    sck_cnt_bit0 <= 1'b1;
end

always@(posedge clk)                            
begin
  sck <= sck_cnt_bit0;
  sck_r <= sck;
end

//------------------------------------------------
//--sdi
//------------------------------------------------
always@(posedge clk) 
begin
  if(tx_en)
    tx_data_r <= tx_data;
  else if((sck_cnt_bit0==1'b0)&&(sck==1'b1)&&(sck_r==1'b0))
    tx_data_r <= {tx_data_r[6:0],1'b1};
end

assign sdi = tx_data_r[7];

//------------------------------------------------
//--sdo
//------------------------------------------------
always@(posedge clk) 
begin
  if((sck_cnt_bit0==1'b1)&&(sck==1'b0))
    rx_data_r <= {rx_data_r[6:0],sdo};  
end

always@(posedge clk) 
begin
  if(({sck_cnt_bit0,sck,sck_r}==3'b110) || (({sck_cnt_bit0,sck,sck_r}==3'b001)&&(csen_r==1'b1)))
    rx_data <= rx_data_r; 
end

always@(posedge clk) 
begin
  if(({sck_cnt_bit0,sck,sck_r}==3'b110) || (({sck_cnt_bit0,sck,sck_r}==3'b001))&&(csen_r==1'b1))
    rx_en <= 1'b1;
  else
    rx_en <= 1'b0;
end

//------------------------------------------------
//--scs
//------------------------------------------------
always@(posedge clk) 
begin
  if(csen_r==1'b0)
     scs <= 1'b0;
  else if(sck_cnt<=5'b11110)
     scs <= 1'b0;
  else
     scs <= 1'b1;
end


endmodule
